package cn.zyl.common.redis.config;

import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import redis.clients.jedis.*;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * RedisInitConfig类说明:
 *
 * @author wsz
 * @version v1.0
 * @date 2020-08-03
 */
public class RedisInitConfig {
    public static void main(String[] args) {
        test1();
        test8();
        test9();
    }
    public static void test1(){
        //ip,端口，连接超时，读写超时
        Jedis jedis = new Jedis("localhost",6379,10,10);
        System.out.println("jedis:"+jedis.ping());
        jedis.info();
        //登录
        // jedis.auth(user, password);
        //jedis.auth( password);
        //关闭连接
        jedis.close();
    }
    public static void test2(){
        Jedis jedis = null;
        //连接池配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>();
        String password = "";
        int timeout = 10;
        int port = 6379;
        String host = "localhost";
        //JedisPool 单例
        try (JedisPool jedisPool = new JedisPool(poolConfig, host, port, timeout, password)) {
            //从连接池获取
            jedis = jedisPool.getResource();
            System.out.println("ping:"+jedis.ping());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(null != jedis){
                //如果使用jedisPool.close操作不是关闭连接，代表归还连接池
                jedis.close();
            }
        }
    }
    public static void test3(){
        //连接池配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>();
        // 设置最大连接数为默认值的5倍
        poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);
        // 设置最大空闲连接数为默认值的3倍
        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);
        // 设置最小空闲连接数为默认值的2倍
        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);
        // 设置开启jmx功能
        poolConfig.setJmxEnabled(true);
        // 设置连接池没有连接后客户端的最大等待时间(单位为毫秒)
        poolConfig.setMaxWaitMillis(3000);
        String password = "";
        int timeout = 10;
        int port = 6379;
        String host = "localhost";
        //JedisPool 单例
        try (JedisPool jedisPool = new JedisPool(poolConfig, host, port, timeout, password)) {

        }
    }
    /** 借助jedis的pipeline模拟批量删除*/
    public static void test4(List<String> keys){
        //ip,端口，连接超时，读写超时
        Jedis jedis = new Jedis("localhost",6379,10,10);
        System.out.println("ping:"+jedis.ping());
        //生成pipeline对象
        Pipeline pipeline = jedis.pipelined();
        //装载删除命令，注意此时命令并未真正执行
        for (String key : keys) {
            pipeline.del(key);
        }
        //执行命令 pipeline.sync();或者
        List<Object> res = pipeline.syncAndReturnAll();
        //输出执行结果
        res.forEach(System.out::println);
        //关闭连接
        jedis.close();
    }
    /** 执行Lua脚本和redis-cli十分类似*/
    public static void test5(String key){
        //ip,端口，连接超时，读写超时
        Jedis jedis = new Jedis("localhost",6379,10,10);
        System.out.println("ping:"+jedis.ping());
        //lua脚本
        String script = "return redis.call('get',KEYS[1])";
        Object res = jedis.eval(script, 1, key);
        System.out.println(res);
        //关闭连接
        jedis.close();
    }
    /** 执行Lua脚本和redis-cli十分类似*/
    public static void test6(String key){
        //ip,端口，连接超时，读写超时
        Jedis jedis = new Jedis("localhost",6379,10,10);
        System.out.println("ping:"+jedis.ping());
        //lua脚本
        String script = "return redis.call('get',KEYS[1])";
        //脚本加载到redis。返回脚本sha1
        String scriptSha = jedis.scriptLoad(script);
        //根据脚本sha1、键的个数、相关参数，执行脚本
        Object res = jedis.evalsha(scriptSha, 1, key);
        System.out.println(res);
        //关闭连接
        jedis.close();
    }
    /** 执行Lua脚本和redis-cli十分类似*/
    public static void test7(){
        JedisCluster cluster = null;
        //一般选用slave of从IP+端口进行增删改查，不用master
        Set<HostAndPort> nodes = new LinkedHashSet<>();
        nodes.add(new HostAndPort("", 6379));
        //连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        //最大空闲连接数，默认8个
        config.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE);
        //最大连接数，默认8个
        config.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL);
        //最小空闲连接数，默认0个
        config.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE);
        //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
        config.setMaxWaitMillis(GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS);
        //对拿到的connection进行validateObject校验
        config.setTestOnBorrow(true);
        cluster = new JedisCluster(nodes, 10,10 , 10, "", config);
        System.out.println(cluster.get("name"));
        cluster.getClusterNodes().get("").getResource().ping();
        /*可能出现的异常
        1、DENIED Redis is running in protected mode because protected mode is enabled...
        解决方法：redis.conf默认禁止外网访问，修改”protected-mode yes”为“protected-mode no”
        2、No more cluster attempts left.
        解决方法：redis设置集群时，服务器没有配置开启集群总线端口（redis端口+10000），如果redis-cli端口有7000-7005，则集群总线端口为17000-17005，服务器7000-70005、17000-17005端口都要打开
        3、No reachable node in cluster
        解决方法：查看redis.conf 的 "bind xxxxxxx" 是否限制了IP访问，注销bind则可以任意IP访问服务器Redis*/
        cluster.close();
    }
    /**Redisson*/
    public static void test8(){
        System.out.println("++++++++++++++");
        Config config = new Config();
        config.useSingleServer()
                .setTimeout(1000000)
                .setAddress("redis://127.0.0.1:6379");
        RedissonClient client = Redisson.create(config);
        System.out.println("Redisson:"+client.getNodesGroup().getNode("redis://127.0.0.1:6379").ping());
        //关闭
        client.shutdown();
    }
    public static void test9(){
        System.out.println("_______________");
        // <1> 创建单机连接的连接信息
        RedisURI redisUri = RedisURI.builder()
                .withHost("localhost")
                .withPort(6379)
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        //创建客户端
        RedisClient client =  RedisClient.create(redisUri);
        // <3> 创建线程安全的连接
        StatefulRedisConnection<String, String> connection = client.connect();
        // <4> 创建同步命令（异步 RedisAsyncCommands；反应式 RedisReactiveCommands)
        RedisCommands<String, String> redisCommands = connection.sync();
        System.out.println("lettuce:"+redisCommands.ping());
    }
}
